package com.jplus.framework.mvc.handler;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.jplus.framework.bean.BeanHandle;
import com.jplus.framework.bean.annotation.Component;
import com.jplus.framework.mvc.DataContext;
import com.jplus.framework.mvc.action.Handler;
import com.jplus.framework.mvc.annotation.Param;
import com.jplus.framework.mvc.handler.param.ParamWatcher;
import com.jplus.framework.util.ClassUtil;
import com.jplus.framework.util.FormatUtil;

/**
 * 默认 Handler 调用器[单例]
 *
 * @author Yuanqy
 * @author huangyong
 */
@Component
public class HandlerInvoker {

	private ViewResolver viewResolver = new ViewResolver();

	/**
	 * 执行Action实现类
	 */
	public void invokeHandler(HttpServletRequest request, HttpServletResponse response, Handler handler) throws Exception {
		// 获取 Action 相关信息
		Class<?> actionClass = handler.getActionClass();
		// 从 BeanHandle 中获取 Action 实例
		Object actionInstance = BeanHandle.getBean(actionClass);
		// 创建 Action 方法的参数列表
		List<Object> actionMethodParamList = createPathParamList(handler);
		// 调用 Action 方法
		Object actionMethodResult = handler.getActionMethod().invoke(actionInstance, actionMethodParamList.toArray());
		// 解析视图
		viewResolver.resolveView(request, response, actionMethodResult);
	}

	private List<Object> createPathParamList(Handler handler) throws Exception {
		Method actionMethod = handler.getActionMethod();
		// == 执行观察者，自定义类型入参[如果有的话]
		List<Object> tempList = ParamWatcher.doWatcher(handler);
		if (tempList != null && tempList.size() > 0)
			return tempList;
		// == 如果没有入参，就不要组装了
		if (actionMethod.getParameterTypes().length == 0)
			return Arrays.asList(new Object[] {});
		// == 执行默认9种Action入参=========================
		Map<String, String> map = handler.getRequestRestful();
		Iterator<String> iter = map.values().iterator();
		Class<?>[] pcs = actionMethod.getParameterTypes();
		Annotation[][] ans = actionMethod.getParameterAnnotations();
		List<Object> paramList = new ArrayList<Object>();
		boolean m = map.size() > 0;
		for (int i = 0; i < pcs.length; i++) {
			Class<?> cla = pcs[i];
			Object val = null;
			// ==1,按注解赋值[一个方法参数可能有多个注解，所以循环取]
			Param p = null;
			for (Annotation an : ans[i]) {
				if (an instanceof Param) {
					p = (Param) an;
					break;
				}
			}
			if (p != null) {
				String param = p.value();
				val = DataContext.getRequest().getParameter(param);
				if (m && FormatUtil.isEmpty(val))
					val = map.get(param);
			}
			// ==2,按类型赋值[默认4钟http对象类型]
			if (FormatUtil.isEmpty(val)) {
				if (cla.equals(HttpServletRequest.class))
					val = DataContext.getRequest();
				else if (cla.equals(HttpServletResponse.class))
					val = DataContext.getResponse();
				else if (cla.equals(ServletContext.class))
					val = DataContext.getServletContext();
				else if (cla.equals(HttpSession.class))
					val = DataContext.getSession();
			}
			// ==3,按restful参数赋值
			if (m && FormatUtil.isEmpty(val)) {
				val = iter.next();
			}

			// == 类型格式化 =======================
			if (!FormatUtil.isEmpty(val)) {
				val = convertType(val, cla);
			}
			paramList.add(val);
		}
		return paramList;
	}

	// 转换参数类型(支持5种类型：int/Integer、long/Long、double/Double、BigDecimal、String)
	private Object convertType(Object param, Class<?> paramType) {
		if (ClassUtil.isInt(paramType)) {
			return FormatUtil.toInt(param);
		} else if (ClassUtil.isLong(paramType)) {
			return FormatUtil.toLong(param);
		} else if (ClassUtil.isDouble(paramType)) {
			return FormatUtil.toDouble(param);
		} else if (ClassUtil.isDecimal(paramType)) {
			return FormatUtil.toDecimal(param);
		} else if (ClassUtil.isString(paramType)) {
			return FormatUtil.toString(param);
		}
		return param;
	}
}
